package com.tbit.uqbike.client.ordertrace;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 订单状态机
 *
 * @author <a href="mailto:chen.chaoxiong@tbit.com.cn">ChenChaoXiong</a>
 * @since 2024/7/2
 */
@Slf4j
public class OrderStateMachine {

    private String traceId;
    private OrderStage stage;
    private final StateTransitionComponent transitionComponent;

    private OrderStateMachine(OrderStage stage,StateTransitionComponent transitionComponent,String traceId) {
        this.stage = stage;
        this.transitionComponent = transitionComponent;
        this.traceId = traceId;
    }




    private List<Snapshot> snapshots = new ArrayList<>();

    public List<Snapshot> getSnapshots() {
        return Collections.unmodifiableList(snapshots);
    }


    public static OrderStateMachine create(OrderStage stage,StateTransitionComponent transitionComponent,String traceId) {
        log.info("build order state machine with stage: {}", stage);
        return new OrderStateMachine(stage,transitionComponent,traceId);
    }

    /**
     * 处理事件
     *
     * @param event 事件
     */
    public EventHandleResult handleEvent(Event event,String requestId) {
        log.info("traceId {}  requestId {}  stage {} handle event: {}",traceId,requestId, stage, event);

        OrderStage newStage =null;
        try {
            newStage = transitionComponent.getNextStage(stage, event);
        } catch (InvalidTransitionException e) {
            String format = "traceId: %s handle event {} fail,errorMsg {} %s";
            String message = String.format(format, traceId,JSON.toJSONString(event) ,e.getMessage());
            log.error(message);
            return EventHandleResult.reject(message);
        }
        OrderStage oldStage = updateStage(newStage);
        Snapshot snapshot = createSnapshot(oldStage, newStage, event,requestId);
        log.info("traceId {}  requestId {}  stage {} handle event: {} success,snapshot {}",traceId,requestId, stage, event,JSON.toJSONString(snapshots));
        addSnapshot(snapshot);
        return EventHandleResult.accept();
    }



    private OrderStage updateStage(OrderStage newStage) {
        log.info("update stage from {} to {}", stage, newStage);
        OrderStage oldStage = stage;
        stage = newStage;
        return oldStage;
    }


    private Snapshot createSnapshot(OrderStage oldStage, OrderStage newStage, Event event, String requestId) {
        log.info("create snapshot, old stage: {}, new stage: {}, rquestId: {},event: {}", oldStage, newStage, requestId,event);
        return Snapshot.builder()
                                    .currentStage(newStage)
                                    .previousStage(oldStage)
                                    .event(event)
                                    .triggerTime(LocalDateTime.now())
                                    .requestId(requestId)
                                    .build();
    }

    private void addSnapshot(Snapshot snapshot) {
        snapshots.add(snapshot);
    }

    /**
     * 获取当前状态
     *
     * @return 当前状态
     */
    public OrderStage getStage() {
        return stage;
    }


    public boolean accept(Event event){
        return transitionComponent.accept(stage,event);
    }


    @Override
    public String toString() {
        return "OrderStateMachine{" +
                "state=" + stage +
                ", snapshots=" + JSON.toJSONString(snapshots) +
                '}';
    }

}
